home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
pcr
/
pcr4_4.lha
/
DIST
/
gc
/
GCcheck_ptr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-09
|
7KB
|
227 lines
/* begincopyright
Copyright (c) 1988,1990 Xerox Corporation. All rights reserved.
Use and copying of this software and preparation of derivative works based
upon this software are permitted. Any distribution of this software or
derivative works must comply with all applicable United States export
control laws. This software is made available AS IS, and Xerox Corporation
makes no warranty about the software, its performance or its conformity to
any specification. Any person obtaining a copy of this software is requested
to send their name and post office or electronic mail address to:
PCR Coordinator
Xerox PARC
3333 Coyote Hill Rd.
Palo Alto, CA 94304
Parts of this software were derived from code bearing the copyright notice:
Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
This material may be freely distributed, provided this notice is retained.
This material is provided as is, with no warranty expressed or implied.
Use at your own risk.
endcopyright */
/* Check whether p points to a valid unmarked object. Continue to the */
/* next iteration if not. Set h to point to the beginning of the block */
/* containing p. Set word_no to the offset of the beginning of the */
/* object. Set sz to the size of the object in words. */
/* Set the bool variable is_atomic appropriately. */
/* Assumes surrounding declarations "long word_no; struct hblk *h". */
/* If SEPARATE_HEADERS is defined, we assume a surrounding decl */
/* "register struct hblkhdr * hhdr" and set hhdr to the header for */
/* the block containing p. */
/* We continue to the next iteration by invoking the CONTINUE macro. */
/* If CONTINUE_M is defined, we use it when we find something */
/* that looks like a marked object. */
/* This is an include file because it is used twice, and in at least */
/* one case we may not be able to afford the procedure calling */
/* overhead (except maybe on a SPARC). */
/* Assumes that quicktest(p) holds. */
# ifndef CONTINUE_M
# define CONTINUE_M CONTINUE
# define DEFINED_CONTINUE_M
# endif
{
# ifdef RESTRICTED_INTERIOR_POINTERS
register unsigned long orig_p = (unsigned long)p;
# endif
register char * map_ptr;
register int map_entry;
/* if not a pointer to obj on heap, skip it */
if (((char *) p) >= GC_heaplim) {
CONTINUE;
}
h = HBLKPTR(p);
# ifndef INTERIOR_POINTERS
/* Check mark bit first, since this test is much more likely to */
/* fail than later ones. */
word_no = WORD_NO(p,h);
# ifdef SEPARATE_HEADERS
hhdr = HDR(h);
if (hhdr == (struct hblkhdr *)0) {
CONTINUE;
}
if (mark_bit_from_hdr(hhdr, word_no)) {
CONTINUE_M;
}
# else
if (mark_bit(h, word_no)) {
CONTINUE_M;
}
# endif
# endif
# ifdef INTERIOR_POINTERS
if (!is_hblk(h)) {
char m = get_map(h);
/* Skip over any continuation blocks: */
while (m > 0 && m < 0x7f) {
h -= m;
m = get_map(h);
}
if (m == HBLK_INVALID) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Pointer to non-heap loc: %X\n", p);
# endif
CONTINUE;
}
}
# ifdef SEPARATE_HEADERS
hhdr = HDR(h);
# endif
/* Force p to point to a longword aligned entity */
p = (struct obj *)(((long)p) & ~(BYTES_PER_WORD - 1));
word_no = WORD_NO(p,h);
# if !defined(SEPARATE_HEADERS) || HDR_BYTES != 0
if (word_no < HDR_WORDS) {
CONTINUE;
}
# endif
# else
if (!is_hblk(h)) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Pointer to non-heap loc: %X\n", p);
# endif
CONTINUE;
}
# endif
# ifdef SEPARATE_HEADRERS
sz = hb_sz_from_hdr(hhdr);
# else
sz = hb_sz(h);
# endif
if (sz < 0) {
sz = -sz;
is_atomic = TRUE;
} else {
is_atomic = FALSE;
}
if (sz <= MAXOBJSZ) {
if ((map_ptr = obj_map[sz]) == (char *) 0) {
# ifdef COUNT_CACHE_HITS
map_cache_misses++;
# endif
# ifdef INTERIOR_POINTERS
word_no = adjusted_word_no(word_no,sz);
# else
if (!is_proper_obj(word_no,sz)) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Bad pointer to heap block: %X,sz = %d\n",p,sz);
# endif
CONTINUE;
}
# endif
if (word_no + sz > BYTES_TO_WORDS(HBLKSIZE)) {
/*
* Note that we dont necessarily check for pointers to the block
* header. This doesn't cause any problems, since we have mark
* bits allocated for such bogus objects.
* We have to check for references past the last object, since
* marking from uch an "object" could cause an invalid memory
* reference.
*/
# ifdef REPORT_FAILURE
GC_vprintf("-> Bad pointer to heap block: %X,sz = %d\n",p,sz);
# endif
CONTINUE;
}
} else /* we have a map of the block */ {
map_entry = map_ptr[word_no];
# ifdef COUNT_CACHE_HITS
map_cache_hits++;
# endif
if (map_entry == OBJ_INVALID) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Bad pointer to mapped heap block: %X,sz = %d\n",
p,sz);
# endif
CONTINUE;
}
# ifdef INTERIOR_POINTERS
word_no -= map_entry;
# endif
}
} else /* large objects */ {
# ifdef INTERIOR_POINTERS
if (word_no >= HDR_WORDS + sz) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Bad pointer to l.o. heap block: %X,sz = %d\n",
p,sz);
# endif
CONTINUE;
}
word_no = HDR_WORDS;
# else
if (word_no != HDR_WORDS) {
# ifdef REPORT_FAILURE
GC_vprintf("-> Bad pointer to l.o. heap block: %X,sz = %d\n",p,sz);
# endif
CONTINUE;
}
# endif
}
# ifdef INTERIOR_POINTERS
# ifdef SEPARATE_HEADERS
if (mark_bit_from_hdr(hhdr, word_no)) {
CONTINUE_M;
}
# else
if (mark_bit(h, word_no)) {
CONTINUE_M;
}
# endif
# endif
# ifdef RESTRICTED_INTERIOR_POINTERS
/* Must still check that the offset is actually valid */
{
register long offset = ((char *)orig_p)
- (((char *)h) + WORDS_TO_BYTES(word_no));
if (offset >= MAX_OFFSET || !valid_offsets[offset]) {
# ifdef REPORT_FAILURE
GC_vprintf(
"-> Bad offset into object %X,sz= %d, offset= %d\n",
orig_p,sz,offset);
# endif
CONTINUE;
}
}
# endif
}
# ifdef DEFINED_CONTINUE_M
# undef CONTINUE_M
# undef DEFINED_CONTINUE_M
# endif